﻿#region Usings

using System;
using System.IO;
using System.Text;
using System.Xml;
using Yandex.Market.Api.Model;
using Yandex.Market.Api.Validation;
using Yandex.Market.Api.YmlSerialization;

#endregion

namespace Yandex.Market.Api
{
    /// <summary>
    ///   Класс для сохранения объекта <c>YmlCatalog</c> в xml
    /// </summary>
    public static class YmlCatalogSerializer
    {
        /// <summary>
        ///   Сериализует экземпляр объекта <c>YmlCatalog</c> в поток<br />
        /// </summary>
        /// <param name = "catalog">Экземпляр объекта <c>YmlCatalog</c></param>
        /// <param name = "outStream">Выходной поток</param>
        /// <param name = "validate">Определяет будет ли производиться валидация объекта <c>YmlCatalog</c></param>
        public static void Serialize(YmlCatalog catalog, Stream outStream, bool validate)
        {
            YmlSerializer ymlSerializer = new YmlSerializer(typeof(YmlCatalog),
                                                            YmlExceptionHandlingPolicies.DoNotThrow,
                                                            YmlExceptionTypes.Ignore,
                                                            YmlSerializationOptions.DontSerializeNullObjects);

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.GetEncoding("windows-1251");
            settings.Indent = true;

            using(XmlWriter xmlWriter = XmlWriter.Create(outStream, settings))
            {
                xmlWriter.WriteProcessingInstruction("xml", "version='1.0' encoding='windows-1251'");
                xmlWriter.WriteDocType("yml_catalog", null, "shops.dtd", null);
                string validationErrors = "";
                bool isValid = true;

                if(validate)
                    isValid = Validator.ValidateYmlCatalog(catalog, out validationErrors);

                if(!isValid)
                {
                    xmlWriter.WriteComment(string.Format("Validation Errors:{0}{1}",
                                                         Environment.NewLine,
                                                         validationErrors));
                    xmlWriter.WriteRaw(Environment.NewLine);
                }

                string serializedObject = ymlSerializer.Serialize(catalog);

                if(ymlSerializer.ParsingErrors.ContainsAnyError)
                    xmlWriter.WriteComment(string.Format("Serialization Errors:{0}{1}",
                                                         Environment.NewLine,
                                                         ymlSerializer.ParsingErrors));

                xmlWriter.WriteRaw(Environment.NewLine);
                xmlWriter.WriteRaw(serializedObject);
                xmlWriter.Flush();
                xmlWriter.Close();
            }
        }

        /// <summary>
        ///   Сериализует экземпляр объекта <c>YmlCatalog</c> в файл
        /// </summary>
        /// <param name = "catalog">Экземпляр объекта <c>YmlCatalog</c></param>
        /// <param name = "path">Полный путь к файлу</param>
        /// <param name = "validate">Определяет будет ли производиться валидация объекта <c>YmlCatalog</c></param>
        public static void Serialize(YmlCatalog catalog, string path, bool validate)
        {
            using(Stream outStream = new FileStream(path, FileMode.Create))
                Serialize(catalog, outStream, validate);
        }

        /// <summary>
        ///   Сериализует объект <c>YmlCatalog</c> в строку
        /// </summary>
        /// <param name = "catalog">Экземпляр объекта <c>YmlCatalog</c></param>
        /// <param name = "validate">Определяет будет ли производиться валидация объекта <c>YmlCatalog</c></param>
        /// <returns>Строка, содержащая YML описание</returns>
        public static string Serialize(YmlCatalog catalog, bool validate)
        {
            using(MemoryStream memoryStream = new MemoryStream())
            {
                Serialize(catalog, memoryStream, validate);
                memoryStream.Seek(0, SeekOrigin.Begin);
                using(StreamReader streamReader = new StreamReader(memoryStream, Encoding.GetEncoding("windows-1251")))
                    return streamReader.ReadToEnd();
            }
        }
    }
}